#!/bin/bash
# shellcheck disable=SC2068
# shellcheck disable=SC2164
# shellcheck disable=SC2010
# shellcheck disable=SC2063
# shellcheck disable=SC2062
# shellcheck disable=SC2035
rpm_name=$1
rpm_branch=$2
patch_path=$3
source_path=$4
cve_num=$5
path_file_name=""
install_retry_count=0
# The rpm package that needs to be installed when compiling
requires_rpms=""
spec_file=""
home_path=$(
  cd ~
  pwd -P
)
root_build_path=${home_path}/"rpmbuild"
current_path=$(
  cd "$(dirname "$0")"
  pwd
)
. ${current_path}/common.sh

function check_patch() {
  if [[ -z ${patch_path} ]]; then
    echo "[ERROR] Input patch is null"
    exit 1
  fi
  for patch in ${patch_path[@]}/$cve_num; do
    if [[ ! -d ${patch} ]]; then
      echo "[ERROR] ${patch} is not found"
      exit 1
    fi
  done
  if [ "`ls -A ${patch_path}/$cve_num`" = "" ];then
    echo "补丁未下载"
    exit 1
  fi
  for patch in `ls ${patch_path[@]}/$cve_num`; do
    if [[ ${patch} == fix*.tmp ]]; then
      echo "补丁下载错误"
      rm -f $patch_path/$cve_num/$patch
      exit 1
    fi
  done
  
}

function check_local() {
  if [[ ! -d ${source_path} ]]; then
    echo "[ERROR] The source package path ${source_path} does not exist"
    exit 1
  fi
}

function check_remote() {
  if [[ -z ${rpm_name} ]] || [[ -z ${rpm_branch} ]]; then
    echo "[ERROR] Incorrect input,Please use [ /bin/bash add_patch.sh 'name of package' 'branch of package' 'path of patch file']"
    exit 1
  fi
}

function pre_env_build() {
  echo "[INFO] Create root path of rpmbuild"
  if [[ ! -d ${root_build_path} ]]; then
    mkdir -p ${root_build_path}/{BUILD,BUILDROOT,RPMS,SPECS,SOURCES,SRPMS}
  fi
}

function git_clone() {
  echo "[INFO] Start to git clone ${rpm_name}"
  cd ${source_path}
  git clone -b ${rpm_branch} https://gitee.com/src-openeuler/${rpm_name}.git >/dev/null 2>&1
  rpm_path=$(ls | grep ${rpm_name})
  if [[ -z ${rpm_path} ]]; then
    echo "[ERROR] Access https://gitee.com/src-openeuler/${rpm_name}.git clone ${rpm_name} failed, please check path ${source_path}"
    exit 1
  fi

  source_path=${source_path}/${rpm_name}
}

function update_spec() {
  echo "[INFO] Start to update spec file"
  cd ${root_build_path}/SOURCES
  spec_file=$(ls | grep *.spec | grep -v *.bak | grep -v *.update)
  if [[ -z ${spec_file} ]]; then
    echo "[ERROR] spec file is not found"
    exit 1
  fi
  # backup spec
  /bin/cp -rf ${spec_file} ${spec_file}.bak
  # update Release
  release_version=$(grep "Release:" ${spec_file} | awk -F " " '{print $NF}' | tr -cd "[0-9]")
  new_release=$(expr ${release_version} + 1)
  sed -i "s/Release:.*${release_version}/Release:        ${new_release}/" ${spec_file}
  # add Patch***
  last_patch=$(grep "Patch.*:" ${spec_file} | sed -n '$p')
  if [[ -z ${last_patch} ]]; then
    source_row=$(grep -n "Source.*:" ${spec_file} | sed -n '$p' | awk -F ':' '{print $1}')
    sed -i -e "${source_row}G;${source_row}a Patch0000:      ${path_file_name}" ${spec_file}
  else
    last_patch_row=$(grep -n "${last_patch}" ${spec_file} | awk -F ':' '{print $1}')
    last_patch_num=$(echo ${last_patch} | awk -F ':' '{print $1}' | awk -F 'Patch' '{print $2}')
    patch_name_len=${#last_patch_num}
    new_patch_num=$(expr ${last_patch_num} + 1)
    new_patch_num=$(printf "%0${patch_name_len}d" ${new_patch_num})
    sed -i "${last_patch_row}a Patch${new_patch_num}:     ${path_file_name}" ${spec_file}
  fi
  # add %patch
  last_patch_apply=$(grep "%patch.* " ${spec_file} | sed -n '$p')
  if [[ -n ${last_patch_apply} ]]; then
    last_patch_apply_row=$(grep -n "${last_patch_apply}" ${spec_file} | awk -F ':' '{print $1}')
    last_patch_apply_num=$(echo ${last_patch_apply} | awk -F ' ' '{print $1}' | awk -F 'patch' '{print $2}')
    ignore_level_num=$(echo ${last_patch_apply} | awk -F ' ' '{print $2}')
    new_patch_apply_num=$(expr ${last_patch_apply_num} + 1)
    sed -i "${last_patch_apply_row}a %patch${new_patch_apply_num} ${ignore_level_num} " ${spec_file}
  fi
  # add changelog
  change_log_row=$(grep -n '%changelog' ${spec_file} | sed -n '$p' | awk -F ':' '{print $1}')
  date_now=$(env LANG=en_US.UTF-8 date "+%a %b %d %Y")
  version=$(grep 'Version:' ${spec_file} | awk -F ' ' '{print $NF}')
  log_description="- add ${path_file_name}"
  log_title="* ${date_now} robot <robot@robot.com> - ${version}-${new_release}"
  sed -i "${change_log_row}G" ${spec_file}
  sed -i "${change_log_row}a ${log_description}" ${spec_file}
  sed -i "${change_log_row}a ${log_title}" ${spec_file}
  /bin/cp -rf ${root_build_path}/SOURCES/*.spec ${root_build_path}/SPECS
  echo "[INFO] Update spec file success"
}

function mv_source_file() {
  echo "[INFO] Copy source file to ${root_build_path}"
  cd ${source_path}
  spec_file=$(ls | grep *.spec | grep -v *.bak | grep -v *.update)
  /bin/cp -rf ${patch_path}/${cve_num}/* ${root_build_path}/SOURCES
  /bin/cp -rf * ${root_build_path}/SOURCES
}

function rpm_build() {
  echo "[INFO] Start to rpmbuild"
  install_rpm rpm-build rpm
  apt-get -y build-dep ${rpm_name} >/dev/null 2>&1
  dnf builddep -y ${root_build_path}/SPECS/${spec_file} >/dev/null 2>&1
  if [[ $? -eq 0 ]]; then
    echo "[INFO] build dependencies success !!!"
  fi
  rpmbuild -bp ${root_build_path}/SPECS/${spec_file} >./result.log 2>&1
  if [[ $? -eq 0 ]]; then
    log_path="${root_build_path}/SOURCES/result.log"
    fix_load=$(awk '(/fix-cve/){print $0}' $log_path)
    if [[ -n ${fix_load} ]];then
      echo "[INFO] build success !!!"
      exit 0
    else
        echo "补丁未能正确加载,请检查spec文件"
        exit 1
    fi
  elif [[ -n $(grep "Failed build dependencies" ./result.log) ]] && [[ ${install_retry_count} -le 2 ]]; then
    requires_rpms=$(grep -r "is needed by" ./result.log | awk -F " " '{print $1}')
    echo "${requires_rpms}" >./requires_rpms.log
    for rpm in ${requires_rpms[@]}; do
      install_rpm ${rpm} ${rpm}
    done
    install_retry_count=$(expr ${install_retry_count} + 1)
    rpm_build
  else
    # mv -f ${source_path}/${spec_file} ${source_path}/${spec_file}.update
    echo "[ERROR] build failed,log is ${root_build_path}/SOURCES/result.log"
    # exit 1
  fi
}

function get_error_msq(){ 
  echo "[INFO] Start to get_error_msq"
  log_path="${root_build_path}/SOURCES/result.log"
  error_msg=$(awk '(/^[0-9]{1,}/){print $0}' $log_path)
  insert_num=$(awk '(/^[0-9]{1,}/){print $1}' $log_path)
  local_num=$(awk '(/^[0-9]{1,}/){print $4}' $log_path)
  fix_load=$(awk '(/fix-cve/){print $0}' $log_path)
  download_right=$(awk '(/Only garbage was found in the patch input/){print $0}' $log_path)
    if [[ -n ${fix_load} ]];then
        :
        if [[ -z ${download_right} ]];then
            :
            if [[ -n ${error_msg} ]]; then
                :
                if [[ "$insert_num" == "$local_num" ]];then
                    echo "版本不受影响或补丁错误"
                else
                    if [[ ${#insert_num} == 1 ]];then
                        echo "补丁部分可用"
                    else
                        echo "版本不受影响或补丁错误"
                    fi
                fi
            fi
        else
            echo "补丁未能正确加载,请检查补丁内容是否正确下载"
        fi
    else
        echo "补丁未能正确加载,请手动修改spec文件进行验证"
    fi
    exit 1
}

function main() {
  check_patch
  if [[ ${rpm_branch} == "no" ]]; then
    check_local
    pre_env_build
  else
    check_remote
    pre_env_build
    git_clone
  fi
  mv_source_file
  if [[ -n `ls $patch_path/$cve_num` ]]; then
    for patch in `ls ${patch_path[@]}/$cve_num`; do
      if [[ ${patch} == fix-cve-*.patch ]]; then
          path_file_name=$(echo "${patch}" | awk -F "/" '{print $NF}' | awk -F "\\" '{print $NF}')
          update_spec
      fi
    done
    rpm_build
    get_error_msq
  else
    echo "补丁未能下载,请尝试手动下载"
  fi
}
main